package track_formats

import (
	"fmt"
	"strings"
	"time"

	"github.com/pion/rtp"
	"gogs.smarteye.com/servere/gobvrtp/encoder"
	"gogs.smarteye.com/servere/gobvrtp/track"
)

// G726Track g726
// ## 小端 <ASF类型>
// ffplay -f g726le -ar 8000 -ac 1 -code_size 4 -i out.g726
// ## 大端 <RFC3551类型>
// ffplay -f g726   -ar 8000 -ac 1 -code_size 4 -i out.g726
//
// -f #格式
// -ac #音频通道
// -ar #采样率
// -code_size #采样宽度 取值范围 2~5 分别代表 16kbps 24kbps 32kbps 40kbps
type G726Track struct {
	AudioTrack

	BitRate   int // 波特率(16/24/32/40)
	BigEndian bool

	encoder *encoder.AudioEncoder
	decoder *encoder.AudioDecoder
}

func NewG726Track() *G726Track {

	c := &G726Track{
		BigEndian: false,
	}

	param := c.CtlParma()
	param.SetPayloadType(97)
	param.SetCodec(track.CodecIdG726)
	param.SetClockRate(8000)
	param.SetChannel(1)
	param.SetOnReadRTPFunc(c.onRTP)

	return c
}

func (c *G726Track) UnmarshalFormat(ctx *track.FormatContext) error {
	_ = c.AudioTrack.UnmarshalFormat(ctx)

	codecStr := ctx.GetRtpMap().GetSourceCodec()
	switch {
	case strings.HasSuffix(codecStr, "-16"):
		c.SetBitRate(16)
	case strings.HasSuffix(codecStr, "-24"):
		c.SetBitRate(24)
	case strings.HasSuffix(codecStr, "-32"):
		c.SetBitRate(32)
	default:
		c.SetBitRate(40)
	}

	return nil
}

// SetBitRate 波特率(16/24/32/40)  "g726-16" "g726-24"   "g726-32"  "g726-40"
func (c *G726Track) SetBitRate(bitRate int) *G726Track {
	c.BitRate = bitRate
	return c
}

// RTPMap implements Format.
func (c *G726Track) RTPMap() string {
	codec := ""

	if c.BigEndian {
		codec += "AAL2-"
	}

	return fmt.Sprintf("%vG726-%v/8000", codec, c.BitRate)
}

func (c *G726Track) WritePacket(t time.Time, data []byte) error {
	param := c.CtlParma()

	if c.encoder == nil {
		// 初始化编码器
		e := &encoder.AudioEncoder{
			PayloadType:           c.PayloadType(),
			SSRC:                  ToPtr(c.SSRC()),
			InitialSequenceNumber: ToPtr(param.InitialSequenceNumber),
			PayloadMaxSize:        param.PayloadMaxSize,
		}

		_ = e.Init()
		c.encoder = e
	}

	packet, err := c.encoder.Encode(data)
	if err != nil {
		return err
	}

	timestamp, _ := c.CtlParma().RtpTimeEncode(t)
	packet.Timestamp = timestamp

	if err = c.WriteRTP(packet); err != nil {
		return err
	}

	return nil
}

func (c *G726Track) onRTP(_ track.Track, pkt *rtp.Packet) {
	packets, _ := c.Detector(pkt)

	if c.decoder == nil {
		// 初始化解码器
		decoder := &encoder.AudioDecoder{}
		_ = decoder.Init()
		c.decoder = decoder
	}

	for _, packet := range packets {
		if data, err := c.decoder.Decode(packet); err == nil {
			c.onFrame(packet, data)
		}
	}
}

func init() {
	RegisterTrack(track.CodecIdG726, func() track.Track {
		return NewG726Track()
	})
}
